package jmine.tec.web.wicket.component.menu;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.wicket.markup.html.panel.Panel;

/**
 * Componente para criação de menus.
 * 
 * @author katsuo.ogawa
 * @date Jul 5, 2011
 */
public class WicketMenuPanel extends Panel implements MenuPanel {

    private final LinkedHashMap<String, MenuItem> topMenuItems = new LinkedHashMap<String, MenuItem>();

    private final LinkedHashMap<String, String> menuPagesPath = new LinkedHashMap<String, String>();

    /**
     * Construtor
     * 
     * @param id id.
     */
    public WicketMenuPanel(String id) {
        super(id);
    }

    /**
     * Cria a lista do menu. Como o values do HashMap retorna uma coleção não serializável, foi necessário criar esta lista somente depois
     * da criação do menu completo. Também preenche o mapa de PagesPath para breadcrumb.
     */
    public void build() {
        List<MenuItem> itens = new ArrayList<MenuItem>();
        for (MenuItem menuItem : this.topMenuItems.values()) {
            menuItem.build();
            itens.add(menuItem);
        }
        this.add(new MenuBar("menubarLinks", itens));
        this.processPagePath(this.topMenuItems.values());
    }

    /**
     * Processa o mapeamento de PagePath (breadcrumb) para uma lista de MenuItem.
     * 
     * @param collectionMenuItem a lista de MenuItem a ter um PagePath mapeado.
     */
    private void processPagePath(Collection<MenuItem> collectionMenuItem) {
        for (MenuItem menuItem : collectionMenuItem) {
            for (MenuLink link : menuItem.getLinks()) {
                if (link instanceof MenuInternalLink) {
                    Class clazz = ((MenuInternalLink) link).getDestination();
                    String path = link.getPath();
                    this.menuPagesPath.put(clazz.getPackage().getName(), path);
                }
            }
            this.processPagePath(menuItem.getChildren());
        }
    }

    /**
     * Adiciona o PagePath (breadcrumb) de uma página específica.
     * 
     * @param pageClass a Class da página.
     * @param pagePath o PagePath para esta página.
     */
    public void addPagePath(Class pageClass, String pagePath) {
        this.menuPagesPath.put(pageClass.getPackage().getName(), pagePath);
    }

    /**
     * Adiciona um item do menu.
     * 
     * @param menuItem {@link MenuItem}
     */
    public void addMenu(MenuItem menuItem) {
        this.topMenuItems.put(menuItem.getLabel(), menuItem);
    }

    /**
     * Devolve o menuItem filho do menu principal, desiginado pelo caminho passado em <code>path</code>.
     * 
     * @param path o caminho do filho, composto pelos ids separados por :
     * @return o menu com o id especificado por <code>path</code>.
     */
    public MenuItem getMenuItem(String path) {
        int index = path.indexOf(SEPARATOR);
        String label = index >= 0 ? path.substring(0, index) : path;
        MenuItem topMenu = this.topMenuItems.get(label);
        return topMenu != null ? topMenu.getMenu(path.substring(index + SEPARATOR.length())) : null;
    }

    /**
     * Retorna o path para uma página.
     * 
     * @param pageClass a classe da página
     * @return o path para chegar a pagina
     */
    public String[] getPagePath(Class pageClass) {
        String path = this.menuPagesPath.get(pageClass.getPackage().getName());
        if ((path != null) && !path.equals("")) {
            return path.split(SEPARATOR);
        } else {
            return null;
        }
    }
}
